package servlet;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import toolkit.Counter;
import toolkit.Debug;
import toolkit.MultiCounter;
import bean.AbstractBean;
import domain.PizzaManager;

abstract public class AbstractServlet extends HttpServlet
{
	private static final long serialVersionUID = 1L;

	// Static
	
	protected static ArrayList<String> steps = new ArrayList<String>();
	
	private static MultiCounter servletIdentifiers = new MultiCounter();
	
	static
	{
		steps.add("Pizza");
		steps.add("Name");
		steps.add("Money");
		steps.add("Order");
	}
	
	// Instance
	
	protected String className;

	protected String name;
	
	protected long id = nextId();
	
	public AbstractServlet()
	{
		Debug.log("(" + id + ") AbstractServlet()");
		
		className = this.getClass().getName();
		
		className = className.substring(className.lastIndexOf('.') + 1);
		
		name = className.substring(0, className.length() - 7);
	}
	
	private synchronized long nextId()
	{
		Debug.log(className + ".nextId()");
		
		Counter identifier = servletIdentifiers.get(className);
		identifier.increment();
		
		return identifier.count();
	}
	
	@Override
	public void init() throws ServletException
	{
		Debug.log("(" + id + ") " + className + ".init()");
		
		super.init();
	}

	@Override
	public void destroy()
	{
		Debug.log("(" + id + ") " + className + ".destory()");
	}
	
	public PizzaManager getPizzaManager(HttpServletRequest request, HttpServletResponse response)
	{
		HttpSession session = getSession(request, response);
		
		PizzaManager pizzaManager = (PizzaManager) session.getAttribute("pizzaManager");
		
		if (pizzaManager == null)
		{
			pizzaManager = new PizzaManager();
			
			session.setAttribute("pizzaManager", pizzaManager);
		}
		
		return pizzaManager;
	}
	
	public Cookie getCookie(String name, HttpServletRequest request)
	{
		Cookie[] cookies = request.getCookies();
		
		if(cookies == null)
		{
			return null;
		}
		
		for (Cookie cookie: cookies)
		{
			if (cookie.getName().equals(name))
			{
				return cookie;
			}
		}
		
		return null;
	}
	
	public HttpSession getSession(HttpServletRequest request, HttpServletResponse response)
	{
		HttpSession session = request.getSession(true);
		
		// Keep track of the user for 1 year.
		int maxAge = 60 * 60 * 24 * 365;
		
		if (session.isNew())
		{
			new Cookie("JSESSIONID", session.getId());
		}
		
		Cookie[] cookies = request.getCookies();
		
		if (cookies != null)
		{
			for (Cookie cookie: cookies)
			{
				cookie.setMaxAge(maxAge);
				
				response.addCookie(cookie);
			}
		}
		
		session.setMaxInactiveInterval(maxAge);
		
		return session;
	}
	
	@SuppressWarnings("unchecked")
	public Map<String, Object> getPostValues(HttpServletRequest request)
	{
		Map<String, Object> postValues = new HashMap<String, Object>();
		
		Enumeration<String> names = request.getParameterNames();
		
		while (names.hasMoreElements())
		{
			String name = names.nextElement();
			
			postValues.put(name, request.getParameter(name));
		}
		
		return postValues;
	}
	
	@SuppressWarnings("unchecked")
	public AbstractBean getBean()
	{
		try
		{
			Class beanClass = Class.forName("bean." + name + "Bean");
			
			return (AbstractBean) beanClass.newInstance();
		}
		catch (Exception e)
		{
			Debug.log(e);
		}
		
		return null;
	}
	
	@Override
	public void finalize() throws Throwable
	{
		Debug.log("(" + id + ") " + className + ".finalize()");

		super.finalize();
	}
}
